package com.itmck;

import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 使用SpringBoot集成Activiti后，每次启动项目时，会自动部署之前放的bpmn文
 * 件，并且，会在Spring容器中自动注入Activiti的几个核心Service
 */
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests2 {


    @Resource
    private RepositoryService repositoryService;//activiti的资源管理类
    @Resource
    private RuntimeService runtimeService; //activiti的流程运行管理类
    @Resource
    private TaskService taskService;  //activiti的任务管理类
    @Resource
    private HistoryService historyService;  //activiti的历史管理类
    @Resource
    private ManagementService managementService; //activiti的引擎管理类

    /**
     * 启动流程实例
     */
    @Test
    public void testStartProcess() {
        HashMap<String, Object> variables = new HashMap<>();
        variables.put("day", 8);
        // 根据流程定义Id启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myLeave", variables);
        // 输出内容
        System.out.println("流程定义id：" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例id：" + processInstance.getId());
        System.out.println("当前活动Id：" + processInstance.getActivityId());
    }

    /**
     * 查询当前个人待执行的任务
     */
    @Test
    public void testFindPersonalTaskList() {
        // 任务负责人 manager worker financer
        String assignee = "financer";
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("myLeave") //流程Key
                .taskAssignee(assignee)//只查询该任务负责人的任务
                .list();
        for (Task task : list) {
            System.out.println("流程实例id：" + task.getProcessInstanceId());
            System.out.println("任务id：" + task.getId());
            System.out.println("任务负责人：" + task.getAssignee());
            System.out.println("任务名称：" + task.getName());
        }
    }

    // 完成任务
    @Test
    public void completTask() {
        // 根据流程key 和 任务的负责人 查询任务
        // 返回一个任务对象
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myLeave") //流程Key
                .taskAssignee("financer") //要查询的负责人
                .singleResult();


        // 完成任务,参数：任务id
        taskService.complete(task.getId());
    }

    /**
     * 查询流程定义
     */
    @Test
    public void queryProcessDefinition() {
        // 得到ProcessDefinitionQuery 对象
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        // 查询出当前所有的流程定义
        // 条件：processDefinitionKey =evection
        // orderByProcessDefinitionVersion 按照版本排序
        // desc倒叙
        // list 返回集合
        List<ProcessDefinition> definitionList =
                processDefinitionQuery.processDefinitionKey("myLeave")
                        .orderByProcessDefinitionVersion()
                        .desc()
                        .list();
        // 输出流程定义信息
        for (ProcessDefinition processDefinition : definitionList) {
            System.out.println("流程定义 id=" + processDefinition.getId());
            System.out.println("流程定义name=" + processDefinition.getName());
            System.out.println("流程定义 key=" + processDefinition.getKey());
            System.out.println("流程定义Version=" + processDefinition.getVersion());
            System.out.println("流程部署ID=" + processDefinition.getDeploymentId());
        }
    }

    @Test
    public void deleteDeployment() {
        // 流程部署id
        String deploymentId = "90791b87-f101-11ec-a291-00ff7b7dfee4";
        //删除流程定义，如果该流程定义已有流程实例启动则删除时出错
        repositoryService.deleteDeployment(deploymentId);
//        //设置true 级联删除流程定义，即使该流程有流程实例启动也可以删除，设置为false非级连删除方式
//        repositoryService.deleteDeployment(deploymentId, true);
    }


    @Test
    public void exclusiveGatewayTest() {
        // 1、发布流程
        Deployment deployment = repositoryService.createDeployment()
                .name("排他网关流程")
                .addClasspathResource("processes/exclud.bpmn")
                .deploy();

        // 2、启动一个流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("exclusive");

        // 3、查询所有任务
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .list();

        Task task = tasks.get(0);
        // 4、完成费用报销审批环节任务的同时设置流程变量，来告诉Activiti该走哪条线
        Map<String, Object> variables = new HashMap<>();
        variables.put("money", 1600);
        taskService.complete(task.getId(), variables);
    }

    @Test
    public void exclusiveGatewayTest2() {

        Task task = taskService.createTaskQuery()
                .orderByTaskCreateTime()
                .desc()
                .list().get(0);
        if (task != null) {
                System.out.println(task);
            }


    }
}
